package mpp;

import java.util.concurrent.locks.ReentrantLock;

class Ex1q1 {
	static int counter = 0;
	public static void main(String args[]) {
		System.out.println("Starting...");
		int n, i=0;		
		
		try {
			n = Integer.parseInt(args[0]);
		} catch (NumberFormatException ex)
		{
			System.out.println("The argument passed is not a number. Exiting...");
			return;
		} catch (ArrayIndexOutOfBoundsException ex){
			System.out.println("You must enter a thread number. Exiting...");
			return;
		}
		
		
		if (n < 1) {
			System.out.println("Can't have negative number of threads.");
			return;
		}
		
		System.out.println("Number of Threads: "+ n);
		
		MyThread threads[] = new MyThread[n];
		long startTime = System.currentTimeMillis(); 
		
		for (i=0; i<n; i++)
			threads[i] = new MyThread(i);
		
		for (i=0; i<n; i++){
			threads[i].Do();
		}
		
		try{
			for (i=0; i<n; i++){
				threads[i].join();
			}
		} catch (InterruptedException ex){}
		
		System.out.println("Counter Value is: "+counter);
		System.out.format("Finished after %d miliseconds.\n", 
				new Long((System.currentTimeMillis() - startTime)));
	}
}

class MyThread extends Thread
{
	//private static int counter = 0;
	int threadID;
	
	public MyThread(int id) {
		threadID = id;
	}
	
	void Do(){
		int i;
		
		for (i = 0; i < 10000; i++){
			incCounter();
			
		}
	}

	
	void incCounter(){
		int temp;
		temp = Ex1q1.counter;
		temp ++;
		Ex1q1.counter = temp;			
	}
	
}



class Ex1q2 {
	static int counter = 0;
	
	public static void main(String args[]) {
		System.out.println("Starting...");
		int n, i=0;		
		
		try {
			n = Integer.parseInt(args[0]);
		} catch (NumberFormatException ex)
		{
			System.out.println("The argument passed is not a number. Exiting...");
			return;
		} catch (ArrayIndexOutOfBoundsException ex){
			System.out.println("You must enter a thread number. Exiting...");
			return;
		}
		System.out.println("Number of Threads: "+ n);
		
		if (n < 1) {
			System.out.println("Can't have negative number of threads.");
			return;
		}
		
		MyThread2 threads[] = new MyThread2[n];
		long startTime = System.currentTimeMillis(); 
		
		for (i=0; i<n; i++)
			threads[i] = new MyThread2(i);
		
		for (i=0; i<n; i++){
			threads[i].Do();
		}
		
		try{
			for (i=0; i<n; i++){
				threads[i].join();
			}
		} catch (InterruptedException ex){}
		
		System.out.println("Counter Value is: "+counter);
		System.out.format("Finished after %d miliseconds.\n", 
				new Long((System.currentTimeMillis() - startTime)));
	}
	
	
}


class MyThread2 extends Thread
{
	private final ReentrantLock lock = new ReentrantLock();
	
	int threadID;
	
	public MyThread2(int id) {
		threadID = id;
	}
	
	void Do(){
		int i;
		
		for (i = 0; i < 10000; i++){
			incCounter();
		}
	}

	void incCounter(){
		int temp;
		
		lock.lock();
		try {
			temp = Ex1q2.counter;
			temp ++;
			Ex1q2.counter = temp;	
		} finally {
			lock.unlock();
		}
		
		
	}

}


